﻿using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Threading;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using GalaSoft.MvvmLight.Threading;
using MoreEPG.DataAccess;
using MoreEPG.Helper;
using MoreEPG.View;


namespace MoreEPG.ViewModel
{
    
    public class MainViewModel : ViewModelBase
    {

        #region Private Vars

        private Dispatcher UiDisp;
        private bool isBatch = false;
        private bool ButtonCanExecute = true;
        private bool ButtonCanExecuteRun = true;
        private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
        public delegate void UpdateProgressDelegate(int percentage, int recordCount, int flag);
        public delegate void MxfProgressDelegate(int percentage);
        private Core _Core = Core.Instance;
        
        #endregion

        #region Constructor

        public MainViewModel()
        {
            logger.Debug("############ Application Starts ################");
            logger.Debug("Version: " + this.GetType().Assembly.GetName().Version.ToString());
            
            this.InitCommands();
            this.UiDisp = DispatcherHelper.UIDispatcher;
            
            this._Core.UiDisp = this.UiDisp;
            this._Core.UpdateProgressdelegate = new UpdateProgressDelegate(UpdateProgressText);
            this._Core.MxfProgressdelegate = new MxfProgressDelegate(UpdateProgressText);
            string[] args = Environment.GetCommandLineArgs();
            if (args.Contains("-batch") || args.Contains("-Batch"))
            {
                this.UIVisible = false;
                this.isBatch = true;
                logger.Debug("App is in Batch Mode.");
                ConsoleManager.Show();

                Console.WriteLine("Welcome to MoreEPG");
                Console.ReadLine();
                
                OnRun();
                Console.ReadLine();
                logger.Debug("############ Application Close ################");
                Application.Current.Shutdown();
            }
            if (!Properties.Settings.Default.ConfigDone)
            {
                this.ButtonCanExecuteRun = false;
            }
            Messenger.Default.Register<CustomDialogMessage>(
               this,
               m =>
               {
                   SetMsgBox(m);
                   this.ShowWait = true;
               });
        }
        private void ClearLine(int line)
        {
            int oldtop = Console.CursorTop;
            Console.CursorTop = line;
            int oldleft = Console.CursorLeft;
            Console.CursorLeft = 0;
            int top = Console.CursorTop;

            while (Console.CursorTop == top)
            { 
                Console.Write(" "); 
            }
            Console.CursorLeft = oldleft;
            Console.CursorTop = oldtop;
        }


        #endregion

        #region Fields

        private string _Text = "";
        public string Text {
            get
            {
                return this._Text;
            }
            set
            {
                if (this._Text == value)
                {
                    return;
                }

                this._Text = value;
                // Update bindings, no broadcast
                RaisePropertyChanged("Text");

            }
        }

       
        public const string ContentPropertyName = "Content";
        private Uri _Content = new Uri("View/Welcome.xaml", UriKind.RelativeOrAbsolute);
        public Uri Content
        {
            get
            {
                return _Content;
            }

            set
            {
                if (_Content == value)
                {
                    return;
                }

                _Content = value;

                // Update bindings, no broadcast
                RaisePropertyChanged(ContentPropertyName);

                
            }
        }


        public const string ValuePropertyName = "Value";
        private int _Value = 0;
        public int Value
        {
            get
            {
                return _Value;
            }

            set
            {
                if (_Value == value)
                {
                    return;
                }

                _Value = value;
                RaisePropertyChanged(ValuePropertyName);

            }
        }

        public const string VisibilityPropertyName = "visibility";
        private bool _visibility = false;
        public bool visibility
        {
            get
            {
                return _visibility;
            }

            set
            {
                if (_visibility == value)
                {
                    return;
                }

                
                _visibility = value;


                // Update bindings, no broadcast
                RaisePropertyChanged(VisibilityPropertyName);

            }
        }

        public const string ShowWaitPropertyName = "ShowWait";
        private bool _ShowWait = false;
        public bool ShowWait
        {
            get
            {
                return _ShowWait;
            }

            set
            {
                if (_ShowWait == value)
                {
                    return;
                }

                _ShowWait = value;

                // Update bindings, no broadcast
                RaisePropertyChanged(ShowWaitPropertyName);

            }
        }

        #endregion

        #region Commands

        public RelayCommand Options
        {
            get;
            private set;
        }

       

        public RelayCommand Close
        {
            get;
            private set;
        }

        public RelayCommand Run
        {
            get;
            private set;
        }

        public RelayCommand About
        {
            get;
            private set;
        }

        public RelayCommand MCTools
        {
            get;
            private set;
        }

        public RelayCommand Sort
        {
            get;
            private set;
        }

        public RelayCommand ChannelConfig
        {
            get;
            private set;
        }

        public RelayCommand DataSource
        {
            get;
            private set;
        }

        public RelayCommand ChannelSettings
        {
            get;
            private set;
        }
        
        private void InitCommands()
        {
            this.Options = new RelayCommand(
                () => OnOptions(),
                () => ButtonCanExecute);

            this.Close = new RelayCommand(
                () => OnClose(),
                () => ButtonCanExecute);

            this.Run = new RelayCommand(
                () => OnRun(),
                () => ButtonCanExecuteRun);

            this.About = new RelayCommand(
                () => OnAbout());

            this.MCTools = new RelayCommand(
                () => OnMCTools());

            this.Sort = new RelayCommand(
                () => OnSort());

            this.ChannelConfig = new RelayCommand(
                () => OnChannelConfig());

            this.DataSource = new RelayCommand(
                () => OnDataSource());

            this.ChannelSettings = new RelayCommand(
               () => OnChannelSettings());

            //MsgBox Cmds
            this.Yes = new RelayCommand(
                () => OnYes());

            this.No = new RelayCommand(
                () => OnNo());

            this.Ok = new RelayCommand(
                () => OnOk());

            this.Cancel = new RelayCommand(
                () => OnCancel());
        }

        

        
        #endregion

        #region Methods

        private void OnChannelSettings()
        {
            this.Content = new Uri("View/ChannelsView.xaml", UriKind.RelativeOrAbsolute);
        }

        private void OnDataSource()
        {
            this.Content = new Uri("View/DataSourceView.xaml", UriKind.RelativeOrAbsolute);
        }

        private void OnChannelConfig()
        {
            this.Content = new Uri("View/ChannelConfigView.xaml", UriKind.RelativeOrAbsolute);
        }

        private void OnSort()
        {
            this.Content = new Uri("View/Sort.xaml", UriKind.RelativeOrAbsolute);
        }

        private void OnMCTools()
        {
            this.Content = new Uri("View/MCToolsView.xaml", UriKind.RelativeOrAbsolute);
        }

        private void OnAbout()
        {
            this.Content = new Uri("View/AboutView.xaml", UriKind.RelativeOrAbsolute);
        }

        
        private void OnOptions()
        {
            this.Content = new Uri("View/SettingsView.xaml", UriKind.RelativeOrAbsolute);
        }

        private void OnRun()
        {
            BackgroundWorker bg = new BackgroundWorker();
            bg.DoWork += new DoWorkEventHandler(bg_DoWork);
            bg.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bg_RunWorkerCompleted);
            this.visibility = true;
            this.ButtonCanExecute = false;
            this.ButtonCanExecuteRun = false;
            Options.RaiseCanExecuteChanged();
            Close.RaiseCanExecuteChanged();
            bg.RunWorkerAsync();
        }

        private void OnClose()
        {
            var message = new CustomDialogMessage("Close Application ?", CustomMessageBoxImage.Question, CustomMessageBoxButton.YesNo, DialogMessageCallback);
            SetMsgBox(message);
            this.ShowWait = true;
        }

        private void DialogMessageCallback(CustomDialogMessageResult result)
        {
            if (result == CustomDialogMessageResult.Yes)
            {
                logger.Debug("############ Application Close ################");
                Messenger.Default.Send("Close");
            }
            
        }

        private void ShuttdownCallback(CustomDialogMessageResult result)
        {
            App.Current.Shutdown();
        }

        void bg_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this.Value = 0;
            this.Text = "Fertig";
            this.visibility = false;
            this.ButtonCanExecute = true;
            this.ButtonCanExecuteRun = true;
            Options.RaiseCanExecuteChanged();
            Close.RaiseCanExecuteChanged();
            this.Content = new Uri("View/Welcome.xaml", UriKind.RelativeOrAbsolute);
        }


        void bg_DoWork(object sender, DoWorkEventArgs e)
        {
            //try
            //{
            //    this._Core.DoAll();
            //}
            //catch (Exception ex)
            //{
            //    if (!this.isBatch)
            //    {
            //        var message = new CustomDialogMessage(ex.Message, CustomMessageBoxImage.Error, CustomMessageBoxButton.OK, null);
            //        this.UiDisp.BeginInvoke((Action)(() =>
            //            {
            //                Messenger.Default.Send(message);
            //            }));
            //    }
            //    logger.Error(ex.Message);
            //}

            arbeit(this.UiDisp, new UpdateProgressDelegate(UpdateProgressText));
            //MXFWriter writer = new MXFWriter(this.UiDisp, new MxfProgressDelegate(UpdateProgressText));
        }

        private void arbeit(Dispatcher pdDispacher, Delegate _delegate)
        {
            //fake BackgroundWorker
            for (int i = 1; i <= 100; i++)
            {
                int perce = HelperClass.GetPercentage(i, 100);
                if (this.isBatch)
                {
                    Console.CursorTop = 2;
                    logger.Info(string.Format("{0}% von {1}% fertig", perce.ToString(), "100"));
                }
                //pdDispacher.BeginInvoke(_delegate, perce, 100, -1);
                pdDispacher.BeginInvoke(
                    (Action)(() =>
                    {
                        Value = perce;
                        Text = string.Format("{0}% von {1}% Fertig", perce.ToString(), 100);
                    }));
                Thread.Sleep(50);
            }
            
        }

        public void UpdateProgressText(int percentage, int recordCount, int flag)
        {
            this.Value = percentage;
            this.Text = string.Format("{0}% von {1}% fertig", percentage.ToString(), recordCount);
        }
        public void UpdateProgressText(int percentage)
        {
            this.Value = percentage;
            this.Text = string.Format("{0}% von {1}% fertig", percentage.ToString());
        }

        #endregion

        #region Console

        /// <summary>
        /// The <see cref="Console" /> property's name.
        /// </summary>
        public const string UIVisiblePropertyName = "UIVisible";

        private bool _UIVisible = true;
        
        /// <summary>
        /// Gets the Console property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public bool UIVisible
        {
            get
            {
                return _UIVisible;
            }

            set
            {
                if (_UIVisible == value)
                {
                    return;
                }


                _UIVisible = value;

                

                // Update bindings, no broadcast
                RaisePropertyChanged(UIVisiblePropertyName);

               
            }
        }


        #endregion
        
        #region MsgBox Adorner

        private CustomDialogMessage LastDialogMessage { get; set; }

        private void SetMsgBox(CustomDialogMessage m)
        {
            this.customMessageBoxImage = m.customMessageBoxImage;
            this.customMessageBoxButton = m.customMessageBoxButton;
            this.InfoText = m.Content;
            LastDialogMessage = m;
        }

        public const string InfoTextPropertyName = "InfoText";
        private string _InfoText;
        public string InfoText
        {
            get
            {
                return _InfoText;
            }

            set
            {
                if (_InfoText == value)
                {
                    return;
                }


                _InfoText = value;


                // Update bindings, no broadcast
                RaisePropertyChanged(InfoTextPropertyName);


            }
        }

        /// <summary>
        /// The <see cref="visibilityYes" /> property's name.
        /// </summary>
        public const string visibilityYesPropertyName = "visibilityYes";

        private bool _visibilityYes = false;

        /// <summary>
        /// Gets the visibilityYes property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public bool visibilityYes
        {
            get
            {
                return _visibilityYes;
            }

            set
            {
                if (_visibilityYes == value)
                {
                    return;
                }


                _visibilityYes = value;

                // Update bindings, no broadcast
                RaisePropertyChanged(visibilityYesPropertyName);


            }
        }

        /// <summary>
        /// The <see cref="visibilityYes" /> property's name.
        /// </summary>
        public const string visibilityNoPropertyName = "visibilityNo";

        private bool _visibilityNo = false;

        /// <summary>
        /// Gets the visibilityYes property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public bool visibilityNo
        {
            get
            {
                return _visibilityNo;
            }

            set
            {
                if (_visibilityNo == value)
                {
                    return;
                }


                _visibilityNo = value;

                // Update bindings, no broadcast
                RaisePropertyChanged(visibilityNoPropertyName);


            }
        }

        /// <summary>
        /// The <see cref="visibilityYes" /> property's name.
        /// </summary>
        public const string visibilityOkPropertyName = "visibilityOk";

        private bool _visibilityOk = false;

        /// <summary>
        /// Gets the visibilityYes property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public bool visibilityOk
        {
            get
            {
                return _visibilityOk;
            }

            set
            {
                if (_visibilityOk == value)
                {
                    return;
                }


                _visibilityOk = value;

                // Update bindings, no broadcast
                RaisePropertyChanged(visibilityOkPropertyName);


            }
        }

        /// <summary>
        /// The <see cref="visibilityYes" /> property's name.
        /// </summary>
        public const string visibilityCancelPropertyName = "visibilityCancel";

        private bool _visibilityCancel = false;

        /// <summary>
        /// Gets the visibilityYes property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public bool visibilityCancel
        {
            get
            {
                return _visibilityCancel;
            }

            set
            {
                if (_visibilityCancel == value)
                {
                    return;
                }


                _visibilityCancel = value;

                // Update bindings, no broadcast
                RaisePropertyChanged(visibilityCancelPropertyName);


            }
        }

        /// <summary>
        /// The <see cref="Image" /> property's name.
        /// </summary>
        public const string ImagePropertyName = "Image";

        private Uri _Image;

        /// <summary>
        /// Gets the Image property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public Uri Image
        {
            get
            {
                return _Image;
            }

            set
            {
                if (_Image == value)
                {
                    return;
                }


                _Image = value;


                // Update bindings, no broadcast
                RaisePropertyChanged(ImagePropertyName);

            }
        }



        private Uri Info = new Uri("../Images/Info.png", UriKind.RelativeOrAbsolute);
        private Uri Question = new Uri("../Images/Question.png", UriKind.RelativeOrAbsolute);
        private Uri Error = new Uri("../Images/Error.png", UriKind.RelativeOrAbsolute);
        private Uri Alert = new Uri("../Images/Alert.png", UriKind.RelativeOrAbsolute);

        public CustomMessageBoxImage customMessageBoxImage
        {
            set
            {
                switch (value)
                {
                    case CustomMessageBoxImage.Error:
                        this.Image = Error;
                        break;
                    case CustomMessageBoxImage.Information:
                        this.Image = Info;
                        break;
                    case CustomMessageBoxImage.Question:
                        this.Image = Question;
                        break;
                    case CustomMessageBoxImage.Alert:
                        this.Image = Alert;
                        break;
                    case CustomMessageBoxImage.None:
                        break;
                    default:
                        break;
                }
            }
        }

        public CustomMessageBoxButton customMessageBoxButton
        {
            set
            {
                this.visibilityOk = false;
                this.visibilityCancel = false;
                this.visibilityYes = false;
                this.visibilityNo = false;
                switch (value)
                {
                    case CustomMessageBoxButton.OK:
                        this.visibilityOk = true;
                        break;
                    case CustomMessageBoxButton.OKCancel:
                        this.visibilityOk = true;
                        this.visibilityCancel = true;
                        break;
                    case CustomMessageBoxButton.YesNo:
                        this.visibilityYes = true;
                        this.visibilityNo = true;
                        break;
                    case CustomMessageBoxButton.YesNoCancel:
                        this.visibilityYes = true;
                        this.visibilityNo = true;
                        this.visibilityCancel = true;
                        break;
                    default:
                        break;
                }
            }
        }

        public CustomDialogMessageResult result { get; set; }


        public RelayCommand Yes
        {
            get;
            private set;
        }

        public RelayCommand No
        {
            get;
            private set;
        }

        public RelayCommand Ok
        {
            get;
            private set;
        }

        public RelayCommand Cancel
        {
            get;
            private set;
        }


        private void OnYes()
        {
            this.result = CustomDialogMessageResult.Yes;
            this.ShowWait = false;
            LastDialogMessage.ProcessCallback(CustomDialogMessageResult.Yes);
        }

        private void OnNo()
        {
            this.result = CustomDialogMessageResult.No;
            this.ShowWait = false;
            LastDialogMessage.ProcessCallback(CustomDialogMessageResult.No);
        }

        private void OnOk()
        {
            this.result = CustomDialogMessageResult.OK;
            this.ShowWait = false;
            LastDialogMessage.ProcessCallback(CustomDialogMessageResult.OK);
        }

        private void OnCancel()
        {
            this.result = CustomDialogMessageResult.Cancel;
            this.ShowWait = false;
            LastDialogMessage.ProcessCallback(CustomDialogMessageResult.Cancel);
        }



        #endregion


    }

   
}